/* TODO: Read through the rest of http://docs.python.org/extending/newtypes.html and modify this to be able to use
 the method and member tables. */

#include <Python.h>
#include <structmember.h>
#include "SDL/SDL.h"
#include "SDL/SDL_opengl.h"

typedef struct {
    PyObject_HEAD
    /* Type-specific fields go here. */
} gfx_gfxObject;

static PyMethodDef gfxcls_methods[] = {
	{NULL} 			/* Sentinel */
};

static PyMemberDef gfxcls_members[] = {
	{NULL}			/* Sentinel */
};

static PyGetSetDef gfxcls_getsetters[] = {
	{NULL}
};

/* Defintions for special methods. */
/* Destructor (__del__) */
static void gfx_destruct(gfx_gfxObject * self)
{
	/* (X)DECREF anything we need to in here. */
	self->ob_type->tp_free((PyObject *)self);
}

/* OpenGL initialisation function. */
int init_GL(const SDL_VideoInfo * vid)
{
	/* Set the default colour of the screen to black. */
	glClearColor(0,0,0,0);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, vid->current_w, vid->current_h, 0, -1, 1);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	return glGetError() == GL_NO_ERROR;
}

/* Constructor (__init__) */
static int gfx_init(gfx_gfxObject * self, PyObject * args, PyObject * kwds)
{
	SDL_VideoInfo * vid;
	
	if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		fprintf(stderr, "Error: Could not initialise SDL.");
		/* Assuming 1 = Error */
		return 1;
	}

	if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		fprintf(stderr, "Error: Could not initialise SDL.\n");
		return 1;
	}
	fprintf(stderr, "SDL initialisation complete.\n");
	if (!(vid = SDL_GetVideoInfo()))
	{
		fprintf(stderr, "Error: Could not get information about the best video mode.\n");
		return 1;
	}
	fprintf(stderr, "Window information successfully gathered.\n");
	fprintf(stderr, "Current resoloution: %d w, %d h\n", vid->current_w, vid->current_h);
	if (SDL_SetVideoMode(vid->current_w, vid->current_h, 0, SDL_OPENGL) == NULL)
	{
		fprintf(stderr, "Error: Could not create window.\n");
		return 1;
	}
	fprintf(stderr, "Window successfully created.\n");
	if (!init_GL(vid))
	{
		fprintf(stderr, "Error: Could not initialise OpenGL.\n");
		return 1;
	}
	fprintf(stderr, "OpenGL successfully initialised.\n");
	
	SDL_WM_SetCaption( "OpenGL Test", NULL );
	
	/* Copy the rest over from the main method of Main.c. */

	/* Initialize any variables, etc. here. */
	/* Zero indicates success. */
	return 0;
}

/* New method (__new__) */
static PyObject * gfx_new(PyTypeObject * type, PyObject * args, PyObject * kwds)
{
	gfx_gfxObject * self;

	self = (gfx_gfxObject *)type->tp_alloc(type, 0);

	if (self != NULL)
	{
		/* Initialize any default values. Return NULL on error. */
	}

	/* Self will be NULL if we were unsuccessful in allocation. */
	return (PyObject *) self;
}

static PyTypeObject gfx_gfxType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "graphics.Graphics",       /*tp_name*/
    sizeof(gfx_gfxObject),     /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)gfx_destruct,  /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT,        /*tp_flags - We don't want it subclassable.*/
    "The Endian graphics API.",/* tp_doc */
    0,		               /* tp_traverse */
    0,		               /* tp_clear */
    0,		               /* tp_richcompare */
    0,		               /* tp_weaklistoffset */
    0,		               /* tp_iter */
    0,		               /* tp_iternext */
    gfxcls_methods,            /* tp_methods */
    gfxcls_members,            /* tp_members */
    gfxcls_getsetters,         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)gfx_init,        /* tp_init */
    0,                         /* tp_alloc */
    gfx_new,                   /* tp_new */
};

static PyMethodDef gfx_methods[] = {
	{NULL} 			/* Sentinel */
};

#ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC void
#endif

PyMODINIT_FUNC initgraphics(void) {
	PyObject * m;
	
	if (PyType_Ready(&gfx_gfxType) < 0)
	{
		return;
	}

	m = Py_InitModule3("graphics", gfx_methods,
			   "The Endian graphics API.");
	
	Py_INCREF(&gfx_gfxType);
	PyModule_AddObject(m, "Graphics", (PyObject *)&gfx_gfxType);
}
